package com.fenyin.samples.study.jdk.nio.channels.tcp.server.reactor;  

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *@Description: reactor模式实现，主线程
 *@Author:fengzhichao  
 *@Since:2012-11-30  
 *@Version:1.1.0
 */
public class ReactorServer implements Runnable{
	/**Socket通信通道*/
	private ServerSocketChannel serverSocketChannel = null;
	/**事件监听器*/
	private Selector selector = null;  
	/**日志处理实例*/
	private static final Log log = LogFactory.getLog(ReactorServer.class);
	/**服务器端口*/
	private static final int port=19997;

	public ReactorServer(){
		try{
			//创建事件监听器
			selector = Selector.open();
			//创建服务器通信通道
			serverSocketChannel=ServerSocketChannel.open();
			//设置通信模式为非阻塞模式
			serverSocketChannel.configureBlocking(false);
			//绑定服务端口
			serverSocketChannel.socket().bind(new InetSocketAddress(port));
			//通信通道绑定事件到事件监听器
			SelectionKey selectionKey=serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			//事件绑定监听线程
			selectionKey.attach(new Acceptor(serverSocketChannel,selector)); 
			log.info("启动服务器成功");
		}catch(Throwable th){
			log.error("启动服务器异常", th);
			System.exit(-1);
		}
	}

	public void run() {
		//定时轮询处理接受到客户端请求的事件处理，该处可以改造成线程池技术
		//此处存在性能瓶颈，主进程逻辑可以进行优化,由该线程统一调度事件的处理
		while(true){
			try{
				//该方法是个阻塞方法
				selector.select();
				Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); 
				System.out.println("--------------");
				while (iter.hasNext()){
					SelectionKey selectionKey = iter.next(); 
					Runnable task = (Runnable) selectionKey.attachment();
					System.out.println(task);
					dispatch(task); 
					//移除处理完的事件
                    iter.remove();
				}
			}catch(Throwable th){
				log.error("Reactor进程异常", th);
			}
		}
	}
	
	public void dispatch(Runnable runnable) {  
        if (runnable != null) {  
        	//绑定的是Acceptor进程
            runnable.run();  
        }  
    } 
	
	public static void main(String[] args) {  
		//Reactor->Acceptor->Handler
        new Thread(new ReactorServer()).start();  
        
        
//        server                                                    client
//        step1-1      启动服务端，selector.select()  阻塞                  
//        step1-2                                                               发送连接请求
//        step1-3      selector.select()  阻塞解除，处理Acceptor事件            
//        step2-1      selector.select()方法执行,无事件处理                                  
//        step3-1      selector.select()方法阻塞                                                         
//        step3-2                                                               发送数据
//        step3-3      selector.select()  阻塞解除，处理Handler-Read事件 
//        step4-1      selector.select() ,处理Handler-Read事件
//        step4-2                                                               接受数据
        
        
//        服务端API研究
//        ServerSocketChannel     serverSocket通道
//                                register方法
//                                accept方法
//                                configureBlocking方法
        
//        SocketChannel           socket通道
//                                register方法
//                                configureBlocking方法
//                                read方法
//                                write方法
          
//        SelectionKey            通道选择事件
//                                attach方法
//        						  interestOps方法
//                                cancel方法

//        Selector                通道选择器
//                                open方法
//                                select方法
//                                selectedKeys方法
//                                wakeup方法
        
//        ByteBuffer              allocate方法
//                                array方法
//                                wrap方法
        
//        客户端API研究
          
        
        
    } 
}
